/**
 * @file cto_prototipo.h
 * @brief T.D.A. Conjunto de Prototipos
 * 
 * @author Antonio Ruano Cuesta
 * @date Mayo-06
 */
 
 /* Copyright 2010 Antonio Ruano Cuesta
 *
 * This program is free software: you can redistribute it and/or modify it under 
 * the terms of the GNU General Public License as published by the Free Software 
 * Foundation, either version 3 of the License, or (at your option) any later 
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with 
 * this program. If not, see <http://www.gnu.org/licenses/>
*/

#ifndef CTOPROTOTIPO
#define CTOPROTOTIPO

#include "prototipo.h"
#include "imagenppm.h"

/**
 * Es extraño que solo sea necesario el almacenaje y uso de un prototipo por si solo, por ello 
 * se hace imprescindible construir una clase para gestionar conjuntos de prototipos.
 * Esta clase, como es de esperar, necesita almacenar en su interior el número de prototipos de 
 * los que consta, el número de posibles clases (desde 0), el número de atributos y los 
 * prototipos, que se almacenarán en un vector dinámico de prototipos.
 */
class cto_prot{

  private:

	/**
       * @page repConjunto Rep del TDA Conjunto de Prototipos
       *
       * @section invConjunto Invariante de la representación
       *
       * El invariante es \e rep.num_prototipos > 0, rep.num_clases >= 0 y rep.num_atrib > 0.
    */

    unsigned int num_prototipos; /**Número de prototipos del conjunto*/

	unsigned int num_clases; /**Número de posibles clases del conjunto*/

	unsigned int num_atrib; /**Número de atributos de los prototipos del conjunto*/
    
	prot *prototipos; /**Puntero a prot encargado de la reserva de memoria*/

  public:
		
	/**
     * @brief Constructor por defecto de la clase. Pone todos sus campos a 0.
    */
    cto_prot();
		
	/**
     * @brief Constructor de la clase.
     * @param n_prot: número de prototipos.
     * @param n_cl: número de clases.
	 * @param n_atr: número de atributos de cada prototipo.
     * @return crea un conjunto de protótipos con n_prot prototipos, y n_cl posibles clases.
     * @pre n_prot > 0.
    */	
    cto_prot(int n_prot, int n_cl, int n_atr);
		
	/**
     * @brief Constructor de copias de la clase.
     * @param cprot conjunto del que se va a hacer la copia.
    */
	cto_prot(const cto_prot &cprot);
		
	/**
     * @brief Destructor: libera la memoria reservada para el conjunto.
    */
	~cto_prot();

	/**
     * @brief Asigna un conjunto de prototipos (cto) a una variable del tipo cto_prot.
     * @param cto: conjunto a asignar al objeto implícito.
	*/
	cto_prot& operator=(const cto_prot &cto);
	
	/**
     * @brief Inserta un nuevo prototipo en el conjunto.
     * @param prototipo: prototipo de la clase prot a insertar.
	 * @param pos: posición en la que se quiere insertar.
	*/
	void nuevo_prot (prot prototipo, int pos);

	/**
     * @brief Consulta un prototipo.
     * @param pos: posición de la que se quiere extraer el prototipo.
	 * @return Prototipo extraído de la posición indicada.
	*/
	prot get_prot (int pos);

	/**
     * @brief Consulta el número de prototipos.
     * @return Número de prototipos del conjunto.
	*/
	unsigned int get_numprot() const;

	/**
     * @brief Consulta el número de clases posible del conjunto.
     * @return Número de clases del conjunto.
	*/
	unsigned int get_numclas () const;
	
	/**
     * @brief Actualiza el valor del número de clases.
     * @param nclas: numero de clases a almacenar.
	*/
	void set_numclas(unsigned int nclas);

	/**
     * @brief Consulta el número de atributos por prototipo.
     * @return Número de atributos que tiene cada prototipo (todos tienen el mismo número).
	*/
	unsigned int get_numatrib() const;

	/**
     * @brief Lee un fichero de prototipos y lo introduce en el objeto de la clase.
	 * @param fich: Nombre del fichero de prototipos a leer.
    */
	void InsertarDesdeFichero (char *fich);

	/**
     * @brief Almacena el contenido del objeto de la clase en un fichero de prototipos.
	 * @param fich: Nombre con el que se quiere salvar el fichero de prototipos.
    */
	void GuardarEnFichero (char *fich);

	/**
     * @brief Clasifica el conjunto de prototipos almacenado en la clase con el metodo knn,  
	 * tomando como referencia el conjunto de aprendizaje.
	 * @param k: Numero de vecinos a considerar.
	 * @param ctoaprend: Conjunto de aprendizaje.
    */
	void knn (unsigned int k, cto_prot ctoaprend);

	/**
     * @brief Clasifica el conjunto de prototipos almacenado en la clase con el metodo de   
	 * minima distancia euclidea, tomando como referencia el conjunto de aprendizaje.
	 * @param ctoaprend: Conjunto de aprendizaje.
    */
	void ClasifMinDisteuclidea (cto_prot ctoaprend);

	/**
     * @brief Calcula los vectores medios de los atributos del conjunto (uno por clase).  
	 * @return Conjunto de vectores medios resultante.
	 * @pre Para que tenga sentido este metodo, el conjunto ha de estar ya clasificado.
    */
	cto_prot CalculoCtoVectoresMedios();

	/**
	 * @brief Calcula una matriz de confusion comparando el conjunto del objeto de la clase 
	 * con el pasado como parametro. La reserva de memoria de la matriz se hace en el interior.
	 * @param clasificado: conjunto de test clasificado por algun metodo.
	 * @return Puntero a puntero que apunta a la matriz de confusion.
    */
	int **CalculoMatrizConfusion(cto_prot clasificado);

	/**
	 * @brief Realiza una conversion de prototipo a ppm utilizando el valor de las clases 
	 * y una matriz de colores que indica el color asociado a cada clase.
	 * Para una conversion correcta, el prototipo ha de estar clasificado.
	 * @param mapa: mapa de colores (matriz de colores).
	 * @param filas: filas de la nueva imagen PPM.
	 * @param cols: columnas de la nueva imagen PPM.
	 * @pre filas > 0 && cols > 0;
	 *		filas * cols = num_prototipos;
	 * @return Puntero a puntero que apunta a la matriz de confusion.
    */
	ImagenPPM ConversionAPPM(int **mapa, int filas, int cols);
		
};



#endif
